package com.googlecode.stemwijzer.rebind.util;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JMethod;
import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.core.ext.typeinfo.TypeOracle;

/**
 * The Class GeneratorUtil.
 */
public final class GeneratorUtil {

	/**
	 * Discover type properties.
	 * 
	 * @param classType
	 *            the class type
	 * @return a list of public properties that have a getter and a setter
	 */
	public static Map<String, JType> discoverTypeProperties(
			final JClassType classType) {
		if (classType == null) {
			return null;
		}

		JMethod[] methods = classType.getMethods();
		if (methods == null) {
			return null;
		}

		Map<String, JType> properties = new HashMap<String, JType>();
		List<String> getters = new ArrayList<String>();
		Map<String, JType> setters = new HashMap<String, JType>();

		List<JMethod> methodsList = Arrays.asList(methods);

		for (JMethod method : methodsList) {
			if (method.isPublic() && method.getName().startsWith("get")) {
				getters.add(method.getName().substring(3));
			} else if (method.isPublic() && method.getName().startsWith("set")) {
				setters.put(method.getName().substring(3), method
						.getParameters()[0].getType());
			}
		}

		for (String propertyName : setters.keySet()) {
			JType argType = setters.get(propertyName);
			if (getters.contains(propertyName) && argType != null) {
				properties.put(propertyName, argType);
			}
		}
		return properties;
	}

	/**
	 * To upper case initial.
	 * 
	 * @param str
	 *            the str
	 * @return the string
	 */
	public static final String toUpperCaseInitial(final String str) {
		if (str == null || str.isEmpty()) {
			return null;
		}
		if (str.length() == 1) {
			return str.toUpperCase();
		}
		return str.substring(0, 1).toUpperCase().concat(str.substring(1));
	}

	/**
	 * Resolve type.
	 * 
	 * @param typeOracle
	 *            the type oracle
	 * @param clazz
	 *            the clazz
	 * @return the j type
	 * @throws UnableToCompleteException
	 *             the unable to complete exception
	 */
	public static final JType resolveType(TypeOracle typeOracle, Class<?> clazz)
			throws UnableToCompleteException {
		JClassType type = typeOracle.findType(clazz.getName());
		if (type == null) {
			throw new UnableToCompleteException();
		}
		return type;
	}
}
